package com.zh.harmony.fragment;

import java.util.ArrayList;
import java.util.List;

/**
 * Fragment的事务实现
 */
public class BackStackRecord extends FragmentTransaction {
    /**
     * Fragment管理器
     */
    private final FragmentManager mFragmentManager;

    /**
     * 待执行的操作列表
     */
    protected final List<Op> mOps = new ArrayList<>();

    /**
     * 事务操作命令
     */
    static int OP_ADD = 1;
    static int OP_REPLACE = 2;
    static int OP_REMOVE = 3;
    static int OP_HIDE = 4;
    static int OP_SHOW = 5;
    static int OP_DETACH = 6;
    static int OP_ATTACH = 7;

    /**
     * 事务操作
     */
    static class Op {
        int cmd;
        Fragment fragment;

        public Op(int cmd, Fragment fragment) {
            this.cmd = cmd;
            this.fragment = fragment;
        }
    }

    public BackStackRecord(FragmentManager fragmentManager) {
        this.mFragmentManager = fragmentManager;
    }

    @Override
    public void commit() {
        mFragmentManager.enqueueAction(new Runnable() {
            @Override
            public void run() {
                executeOp();
            }
        });
    }

    @Override
    public void commitNow() {
        executeOp();
    }

    /**
     * 执行Op操作
     */
    private void executeOp() {
        for (Op mOp : mOps) {
            if (mOp.cmd == OP_ADD) {
                mFragmentManager.addFragment(mOp.fragment);
            } else if (mOp.cmd == OP_REMOVE) {
                mFragmentManager.removeFragment(mOp.fragment);
            } else if (mOp.cmd == OP_REPLACE) {
                mFragmentManager.replaceFragment(mOp.fragment);
            } else if (mOp.cmd == OP_HIDE) {
                mFragmentManager.hideFragment(mOp.fragment);
            } else if (mOp.cmd == OP_SHOW) {
                mFragmentManager.showFragment(mOp.fragment);
            } else if (mOp.cmd == OP_DETACH) {
                mFragmentManager.detachFragment(mOp.fragment);
            } else if (mOp.cmd == OP_ATTACH) {
                mFragmentManager.attachFragment(mOp.fragment);
            }
        }
        mOps.clear();
    }

    @Override
    public FragmentTransaction add(int containerId, Fragment fragment) {
        doAddOp(containerId, fragment, null);
        return this;
    }

    @Override
    public FragmentTransaction add(int containerId, Fragment fragment, String tag) {
        doAddOp(containerId, fragment, tag);
        return this;
    }

    @Override
    public FragmentTransaction attach(Fragment fragment) {
        doAttachOp(fragment);
        return this;
    }

    @Override
    public FragmentTransaction detach(Fragment fragment) {
        doDetachOp(fragment);
        return this;
    }

    @Override
    public FragmentTransaction replace(int containerId, Fragment fragment) {
        doReplaceOp(containerId, fragment, null);
        return this;
    }

    @Override
    public FragmentTransaction replace(int containerId, Fragment fragment, String tag) {
        doReplaceOp(containerId, fragment, tag);
        return this;
    }

    @Override
    public FragmentTransaction remove(Fragment fragment) {
        doRemoveOp(fragment);
        return this;
    }

    @Override
    public FragmentTransaction show(Fragment fragment) {
        doShowOp(fragment);
        return this;
    }

    @Override
    public FragmentTransaction hide(Fragment fragment) {
        doHideOp(fragment);
        return this;
    }

    //------------------------------ 具体操作 ------------------------------

    void doShowOp(Fragment fragment) {
        if (fragment == null) {
            throw new NullPointerException("Fragment is null");
        }
        addOp(new Op(OP_SHOW, fragment));
    }

    void doHideOp(Fragment fragment) {
        if (fragment == null) {
            throw new NullPointerException("Fragment is null");
        }
        addOp(new Op(OP_HIDE, fragment));
    }

    void doRemoveOp(Fragment fragment) {
        if (fragment == null) {
            throw new NullPointerException("Fragment is null");
        }
        addOp(new Op(OP_REMOVE, fragment));
    }

    void doReplaceOp(int containerId, Fragment fragment, String tag) {
        if (fragment == null) {
            throw new NullPointerException("Fragment is null");
        }
        if (tag != null) {
            fragment.mTag = tag;
        }
        fragment.mContainerId = containerId;
        addOp(new Op(OP_REPLACE, fragment));
    }

    void doAddOp(int containerId, Fragment fragment, String tag) {
        if (fragment == null) {
            throw new NullPointerException("Fragment is null");
        }
        if (tag != null) {
            fragment.mTag = tag;
        }
        fragment.mContainerId = containerId;
        addOp(new Op(OP_ADD, fragment));
    }

    void doAttachOp(Fragment fragment) {
        if (fragment == null) {
            throw new NullPointerException("Fragment is null");
        }
        addOp(new Op(OP_ATTACH, fragment));
    }

    void doDetachOp(Fragment fragment) {
        if (fragment == null) {
            throw new NullPointerException("Fragment is null");
        }
        addOp(new Op(OP_DETACH, fragment));
    }

    void addOp(Op op) {
        mOps.add(op);
    }
}